#include "bluetooth.h"

static uint32_t _g_head = 0;                      // 队列头部
static uint32_t _g_tail = 0;                      // 队列尾部
static BLUETOOTH_MSG _g_msg[BLUETOOTH_MAX] = {0}; // 消息队列
static uint8_t _g_cache[BLUETOOTH_LENGTH] = {0};  // 消息缓存

/**
 * @name 接收消息
 * @description
 * @function
 * @returns {BLUETOOTH_MSG} 消息
 * @requires []
 */
static BLUETOOTH_MSG _bluetooth_recv(void) {
    uint8_t i, xor = 0;
    BLUETOOTH_MSG msg = {0};
    // 校验头尾
    if (_g_cache[0] != BLUETOOTH_HEADER || _g_cache[BLUETOOTH_LENGTH - 1] != BLUETOOTH_TAIL)
        return msg;
    // 数据异或
    for (i = 1; i < 7; ++i)
        xor ^= _g_cache[i];
    // 校验异或
    if (_g_cache[BLUETOOTH_LENGTH - 2] != xor)
        return msg;
    // 解析数据
    msg.type = _g_cache[2];
    msg.msg = _g_cache[3] << 24 | _g_cache[4] << 16 | _g_cache[5] << 8 | _g_cache[6];
    // 清空缓存
    for (i = 0; i < BLUETOOTH_LENGTH; ++i)
        _g_cache[i] = 0;
    // 返回数据
    return msg;
}

/**
 * @name USART发送数据
 * @description
 * @function
 * @param {uint8_t} ch 字符
 * @returns {void}
 * @requires [ch]
 */
static void _usart_send(const uint8_t ch) {
    USART_SendData(BLUETOOTH_USART, ch);
    while (USART_GetFlagStatus(BLUETOOTH_USART, USART_FLAG_TXE) != SET) {}
}

/**
 * @name USART中断
 * @description
 * @function
 * @returns {void}
 * @requires []
 */
void BLUETOOTH_USART_IRQHandler(void) {
    uint8_t i;
    BLUETOOTH_MSG msg;
    // 数据就绪
    if (USART_GetITStatus(BLUETOOTH_USART, USART_IT_RXNE) == SET) {
        // 前移一位
        for (i = 1; i < BLUETOOTH_LENGTH; ++i)
            _g_cache[i - 1] = _g_cache[i];
        // 读取数据
        _g_cache[BLUETOOTH_LENGTH - 1] = USART_ReceiveData(BLUETOOTH_USART);
        // 接收完毕
        if ((msg = _bluetooth_recv()).type) {
            // 队列已满
            if ((_g_tail + 1) % BLUETOOTH_MAX == _g_head) {
                ++_g_head;
                if (_g_head == BLUETOOTH_MAX)
                    _g_head = 0;
            }
            // 插入队列
            _g_msg[_g_tail++] = msg;
            if (_g_tail == BLUETOOTH_MAX)
                _g_tail = 0;
        }
        // 清除标志
        USART_ClearITPendingBit(BLUETOOTH_USART, USART_IT_RXNE);
    }
}

/**
 * @name bluetooth初始化
 * @description
 * @function
 * @returns {void}
 * @requires []
 */
void bluetooth_init(void) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    NVIC_InitTypeDef NVIC_InitStruct = {0};
    USART_InitTypeDef USART_InitStruct = {0};
    // 使能时钟
    BLUETOOTH_RCC_AHBPeriphClockCmd;
    // 配置GPIO
    GPIO_InitStruct.GPIO_Pin = BLUETOOTH_GPIO_Pin;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    // 初始GPIO
    GPIO_Init(BLUETOOTH_GPIO, &GPIO_InitStruct);
    // 配置复用
    GPIO_PinAFConfig(BLUETOOTH_GPIO, BLUETOOTH_USART_TX, BLUETOOTH_GPIO_AF_USART);
    GPIO_PinAFConfig(BLUETOOTH_GPIO, BLUETOOTH_USART_RX, BLUETOOTH_GPIO_AF_USART);
    // 使能时钟
    BLUETOOTH_RCC_APBPeriphClockCmd;
    // 配置USART
    USART_InitStruct.USART_BaudRate = BLUETOOTH_USART_BaudRate;
    USART_InitStruct.USART_WordLength = USART_WordLength_8b;
    USART_InitStruct.USART_StopBits = USART_StopBits_1;
    USART_InitStruct.USART_Parity = USART_Parity_No;
    USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    // 初始USART
    USART_Init(BLUETOOTH_USART, &USART_InitStruct);
    // 优先分组
    SYS_NVIC_PriorityGroupConfig;
    // 配置中断
    USART_ITConfig(BLUETOOTH_USART, USART_IT_RXNE, ENABLE);
    NVIC_InitStruct.NVIC_IRQChannel = BLUETOOTH_USART_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = BLUETOOTH_NVIC_IRQChannelPreemptionPriority;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = BLUETOOTH_NVIC_IRQChannelSubPriority;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    // 初始中断
    NVIC_Init(&NVIC_InitStruct);
    // 使能USART
    USART_Cmd(BLUETOOTH_USART, ENABLE);
}

/**
 * @name 接收消息
 * @description
 * @function
 * @returns {BLUETOOTH_MSG} 消息
 * @requires []
 */
BLUETOOTH_MSG bluetooth_recv(void) {
    BLUETOOTH_MSG msg = {0};
    // 移出队列
    if (_g_head != _g_tail)
        msg = _g_msg[_g_head++];
    if (_g_head == BLUETOOTH_MAX)
        _g_head = 0;
    // 返回数据
    return msg;
}

/***
 * @name 发送消息
 * @description
 * @function
 * @param {BLUETOOTH_MSG} msg 消息
 * @returns {void}
 * @requires [msg]
 */
void bluetooth_send(const BLUETOOTH_MSG msg) {
    uint8_t i, xor = 0, cache[BLUETOOTH_LENGTH];
    // 设置头部
    cache[0] = BLUETOOTH_HEADER;
    // 设置长度
    cache[1] = BLUETOOTH_LENGTH;
    xor ^= cache[1];
    // 消息类型
    cache[2] = msg.type;
    xor ^= cache[2];
    // 消息内容
    cache[3] = (msg.msg >> 24) & 0xff;
    xor ^= cache[3];
    cache[4] = (msg.msg >> 16) & 0xff;
    xor ^= cache[4];
    cache[5] = (msg.msg >> 8) & 0xff;
    xor ^= cache[5];
    cache[6] = msg.msg & 0xff;
    xor ^= cache[6];
    // 校验编码
    cache[BLUETOOTH_LENGTH - 2] = xor;
    // 设置尾部
    cache[BLUETOOTH_LENGTH - 1] = BLUETOOTH_TAIL;
    // 发送数据
    for (i = 0; i < BLUETOOTH_LENGTH; ++i)
        _usart_send(cache[i]);
}
